
#include "drv_systick.h"

static __IO uint8_t enablesystickisr = 0;
static soft_tmr sys_tmr[TMR_COUNT] = {0};

static volatile uint32_t delaycount = 0;
static volatile uint8_t timeoutflag = 0;

__IO int32_t runtime = 0;

extern u32 SystemCoreClock;

static void bsp_softtimerdec(soft_tmr *_tmr)
{
	if (--_tmr->count == 0)
	{
		_tmr->flag = 1;

		if(_tmr->mode == TMR_AUTO_MODE)
		{
			_tmr->count = _tmr->preLoad;
		}
	}
}


void bsp_starttimer(uint8_t _id, uint32_t _period, uint8_t mode)
{
	DISABLE_INT();

	sys_tmr[_id].count = _period;
	sys_tmr[_id].preLoad = _period;
	sys_tmr[_id].flag = 0;
	sys_tmr[_id].mode = mode;

	ENABLE_INT();
}

void bsp_stoptimer(uint8_t _id)
{
	DISABLE_INT();

	sys_tmr[_id].count = 0;
	sys_tmr[_id].flag = 0;
	sys_tmr[_id].mode = TMR_ONCE_MODE;

	ENABLE_INT();
}

uint8_t bsp_checktimer(uint8_t _id)
{
	if (sys_tmr[_id].flag == 1)
	{
		sys_tmr[_id].flag = 0;
		return 1;
	}
	else
	{
		return 0;
	}
}

int32_t bsp_getruntime(void)
{
	int32_t run_time;

	DISABLE_INT();

	run_time = runtime;

	ENABLE_INT(); 

	return run_time;
}

int32_t bsp_checkruntime(int32_t lasttime)
{
	int32_t now_time;
	int32_t time_diff;

	DISABLE_INT();
	now_time = runtime;
	ENABLE_INT();
	
	if (now_time >= lasttime)
	{
		time_diff = now_time - lasttime;
	}
	else
	{
		time_diff = 0x7FFFFFFF - lasttime + now_time;
	}

	return time_diff;
}


static void systick_isr(void)
{
	//static uint8_t count = 0;
	uint8_t i;
	
	if (delaycount > 0)
	{
		if (--delaycount == 0)
		{
			timeoutflag = 1;
		}
	}

	for (i = 0; i < TMR_COUNT; i++)
	{
		bsp_softtimerdec(&sys_tmr[i]);
	}

	runtime++;
	if (runtime == 0x7FFFFFFF)
	{
		runtime = 0;
	}
}

extern void bsp_idle(void);
void bsp_delayms(uint32_t n)
{
	if (n == 0)
	{
		return;
	}
	else if (n == 1)
	{
		n = 2;
	}

	DISABLE_INT();

	delaycount = n;
	timeoutflag = 0;

	ENABLE_INT();

	while (timeoutflag == 0)
	{
	}
}

void bsp_delayus(uint32_t n)
{
    uint32_t ticks;
    uint32_t told;
    uint32_t tnow;
    uint32_t tcnt = 0;
    uint32_t reload;
       
	reload = SysTick->LOAD;                
    ticks = n * (SystemCoreClock / 1000000);
    
    tcnt = 0;
    told = SysTick->VAL;

    while (1)
    {
        tnow = SysTick->VAL;    
        if (tnow != told)
        {    
            if (tnow < told)
            {
                tcnt += told - tnow;    
            }
            else
            {
                tcnt += reload - tnow + told;    
            }        
            told = tnow;

            if (tcnt >= ticks)
            {
            	break;
            }
        }  
    }
} 


void SysTick_Handler(void)
{
	if (enablesystickisr == 0)
	{
		return;
	}
	systick_isr();
}


void systick_init(void)
{
	soft_tmr *tmr = NULL;
	for (tmr = sys_tmr; tmr < &sys_tmr[TMR_COUNT]; tmr++)
	{
		tmr->count = 0;
		tmr->preLoad = 0;
		tmr->flag = 0;
		tmr->mode = TMR_ONCE_MODE;
	}
	SysTick_Config(SystemCoreClock / 1000);
	enablesystickisr = 1;
}

